use std::{any::Any, collections::HashMap};

use common_base::prelude::*;

use crate::ServiceContext;

pub type ServicePluginCreator = unsafe extern "C" fn() -> *mut Box<dyn ServicePlugin>;

#[async_trait::async_trait]
pub trait ServicePlugin: Any + Send + Sync {
    fn get_service_plugin_base(&self) -> &ServicePluginBase;
    fn get_service_plugin_base_mut(&mut self) -> &mut ServicePluginBase;

    fn can_prepare_service(&self, _: &dyn ServiceContext) -> bool {
        true
    }

    fn can_process_service(&self, _: &dyn ServiceContext) -> bool {
        true
    }

    fn can_finish_service(&self, _: &dyn ServiceContext) -> bool {
        true
    }

    async fn prepare_service(&self, srv_ctx: &mut dyn ServiceContext) -> Result<()>;

    async fn process_service(&self, srv_ctx: &mut dyn ServiceContext) -> Result<()>;

    async fn finish_service(&self, srv_ctx: &mut dyn ServiceContext) -> Result<()>;
}

pub struct ServicePluginBase {
    pub(crate) id: String,
    pub(crate) name: String,
    pub(crate) enabled: bool,
    pub(crate) rollback_service: Option<String>,
    pub(crate) property_map: HashMap<String, String>,
}

impl Default for ServicePluginBase {
    fn default() -> Self {
        Self {
            id: Default::default(),
            name: Default::default(),
            enabled: Default::default(),
            rollback_service: Default::default(),
            property_map: Default::default(),
        }
    }
}
